/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-04-03 10:08
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第三章 字符串，向量和数组
 *       3.5 C++内置类型数组
 *       3.5.4 C风格字符串
 * 
 ********************************************************************************************************************************/


#include <iostream>
#include <string>
#include <vector>
#include <cctype>       //是C语言标准库头文件ctype.h的C++语言版本
#include <iterator>     //C++头文件定义了 std::begin(), std::end() 函数用户获取数组的迭代器
#include <cstring>      //是C语言标准库头文件string.h的C++语言版本


int main(int argc, char *argv[])
{
    std::cout << "hello wrold, C-style character string" << std::endl;


    auto *p1 = "string1";
    auto *p2 = "stringp2";


    std::cout << "strlen(p1)" << strlen(p1) << std::endl;
    std::cout << "strlen(p2)" << strlen(p2) << std::endl;

    std::cout << "strcmp(p1,p2)=" << strcmp(p1, p2) << std::endl;




    ///
    /// 3.5.4 节练习
    /// 练习3.37 下面这段程序的适合含义，程序的输出是什么
    ///
    const char ca[] = {'h', 'e', 'l', 'l', 'o', '\0'};   //字符数组，元素的类型是 const char, 没有以空字符结尾，
                                                    //不是C-style 风格的字符串
                                                    //不能使用strlen()的C标准库字符串函数
    const char *cp = ca;                            //使用数组对象，通常情况下编译器会自动把数组名转换为
                                                    //指向数组首元素的指针, *cp = &ca[0];
    while(*cp){                                     //尝试用指针遍历数组ca中字符，遇到空字符结束
        std::cout << *cp << std::endl;                        //因为ca数组没有以空字符结尾，所以循环输出的结果是未定义的
        ++cp;
    }



    ///
    /// 3.5.4 节练习
    /// 练习3.38 在本节中我们提到，将连个指针相加是非法的，而且也没有什么意义，请问为什么两个指针相加没有意义？
    ///
    // 回答: 指针本事是对象，指针间接指向一个类型的对象，指针的值是所间接指向对象的地址
    //       当指针指向同一个数组中的元素或数组中尾元素的下一位置时，两个指针相减是有意义的，它表示右边的运算对象向前移动
    //       多少位置可以追上左侧的运算对象指针
    //
    //
    //
    //



    ///
    /// 3.5.4 节练习
    /// 练习3.39 编写一段程序，比较两个string对象，再编写一段程序比较两个C风格的字符串
    ///

    std::string s1("hello");
    std::string s2("world");
    const char sa1[] = "hello1";
    const char sa2[] = "hello2";

    if(s1 == s2)
        std::cout << "s1 " << s1 << " equal s2 " << s2 << std::endl;
    else{
        std::cout << "s1 " << s1 << " not equal s2 " << s2 << std::endl;

        if(s1 < s2)
            std::cout << "s1 " << s1 << " litter than s2 " << s2 << std::endl;
        else
            std::cout << "s1 " << s1 << " bigger than s2 " << s2 << std::endl;
    }


    if(strcmp(sa1, sa2) == 0)
        std::cout << "sa1 " << std::string(sa1) << " equal sa2 " << std::string(sa2) << std::endl;
    else
        std::cout << "sa1 " << std::string(sa1) << " not equal sa2 " << std::string(sa2) << std::endl;

    #if 0
    else{
        std::cout << "sa1 " << sa1 << " not equal sa2 " << sa2 << std::endl;

        if(s1 < s2)
            std::cout << "sa1 " << sa1 << " litter than s2 " << sa2 << std::endl;
        else
            std::cout << "sa1 " << sa1 << " bigger than s2 " << sa2 << std::endl;
    }
    #endif


    ///
    /// 3.5.4 节练习
    /// 练习3.40 编写一段程序，定义两个字符数组并用字符串字面值初始化它们，接在再定义一个数组厨房前两个数组拼接后的结果
    /// 。使用strcay和strcat把前两个数组内容拷贝到第三个数组中
    ///
    char sa3[64] = "";
    strcat(sa3, sa1);
    strcat(sa3, sa2);
    std::cout << "sa3=" << sa3 << std::endl;




    ///
    /// 3.5.5 节练习
    /// 练习3.41：编写一段程序，用整型数组初始化一个vector对象
    ///

    int ia1[] = {1, 2, 3, 4, 5};
    std::vector<int> ivec1(std::begin(ia1), std::end(ia1));
    for(auto i : ia1)
        std::cout << "ia1[i] " << i << std::endl;
    

    //vector对象使用迭代器，vector容器有成员begin和end放回指向容器首元素的迭代器和容器尾元素下一位置的迭代器
    //迭代器自增运算符，把迭代器从一个元素移动到下一个元素
    //迭代器类似于指针，是对容器重元素的的间接引用
    //解引用一个迭代器可以得到迭代器指示的对象
    for(std::vector<int>::iterator it = ivec1.begin(); it != ivec1.end(); it++)
        std::cout << "ivec use iterator it " << *it << std::endl;

     ///
    /// 3.5.5 节练习
    /// 练习3.42：编写一段程序，将含有整数vector对象拷贝给一个整型数组
    /// 
    int ia2[10] = {};
    int *ip = std::begin(ia2);
    for(auto i : ivec1){
        *ip = i;
        ip++;
    }

    for(auto i : ia2)
        std::cout << "ia2 " << i << std::endl;


    return 0;
}